package com.jsu.clubmanagementsystem.service.application.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jsu.clubmanagementsystem.common.ErrorCode;
import com.jsu.clubmanagementsystem.common.PageQueryRequest;
import com.jsu.clubmanagementsystem.constant.UserConstant;
import com.jsu.clubmanagementsystem.exception.BusinessException;
import com.jsu.clubmanagementsystem.model.dto.userapplication.UserApplicationAddRequest;
import com.jsu.clubmanagementsystem.model.dto.userapplication.UserApplicationQueryRequest;
import com.jsu.clubmanagementsystem.model.entity.*;
import com.jsu.clubmanagementsystem.model.enums.ApplicationTypeEnum;
import com.jsu.clubmanagementsystem.model.enums.ClubMemberRoleEnum;
import com.jsu.clubmanagementsystem.model.enums.ReviewResultEnum;
import com.jsu.clubmanagementsystem.model.vo.userApplication.UserApplicationVO;
import com.jsu.clubmanagementsystem.model.vo.user.UserVO;
import com.jsu.clubmanagementsystem.mapper.UserApplicationMapper;
import com.jsu.clubmanagementsystem.model.vo.review.ReviewVO;
import com.jsu.clubmanagementsystem.service.activity.ActivityService;
import com.jsu.clubmanagementsystem.service.application.UserApplicationService;
import com.jsu.clubmanagementsystem.service.club.ClubMembershipService;
import com.jsu.clubmanagementsystem.service.club.ClubService;
import com.jsu.clubmanagementsystem.service.review.ReviewService;
import com.jsu.clubmanagementsystem.service.user.UserService;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
* @author 24753
* @description 针对表【user_application(用户相关申请)】的数据库操作Service实现
* @createDate 2025-05-17 17:05:45
*/
@Service
public class UserApplicationServiceImpl extends ServiceImpl<UserApplicationMapper, UserApplication>
        implements UserApplicationService {

    @Resource
    private UserService userService;

    @Resource
    private ClubService clubService;

    @Resource
    private ClubMembershipService clubMembershipService;

    @Resource
    private ActivityService activityService;

    @Resource
    @Lazy
    private ReviewService reviewService;

    /**
     * 处理申请
     * @param addRequest
     * @return
     */
    @Override
    public Long processApplication(UserApplicationAddRequest addRequest) {
        ApplicationTypeEnum applicationType = ApplicationTypeEnum.getByCode(addRequest.getType());
        if (applicationType == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "无效的申请类型");
        }
        String reason = addRequest.getReason();
        if (StringUtils.isNotBlank(reason) && reason.length() > 2048) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "申请原因过长");
        }
        if (addRequest.getAdditionalInfo() == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "目标参数为空");
        }

        UserApplication application = new UserApplication();
        BeanUtils.copyProperties(addRequest, application);
        switch (applicationType) {
            case DELETE_USER:
                return addDeleteUserApplication(application);
            case JOIN_CLUB:
                return addJoinClubApplication(application);
            case QUIT_CLUB:
                return addQuitClubApplication(application);
            case ENGAGE_ACTIVITY:
                return addEngageActivityApplication(application);
            case QUIT_ACTIVITY:
                return addQuitActivityApplication(application);
            default:
                throw new BusinessException(ErrorCode.PARAM_ERROR, "无效的申请类型");
        }
    }

    /**
     * 提交账号注销申请
     *
     * @param application
     * @return
     */
    @Transactional
    public Long addDeleteUserApplication(UserApplication application) {
        Long userId = application.getUserId();
        User user = userService.getById(userId);
        if (user.getUserRole().equals(UserConstant.USER_ROLE_MANAGER)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "社长无法直接注销账号");
        }
        QueryWrapper<ClubMembership> clubMembershipQueryWrapper = clubMembershipService.getQueryWrapper(userId, 0L);
        if (clubMembershipService.count(clubMembershipQueryWrapper) > 0) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "用户有未退出的社团");
        }
        List<Activity> activityList = activityService.getActivityListOfUser(userId, 0L);
        if( !activityService.isActivitiesAllEnd(activityList)){
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "用户有未完成的社团活动");
        }
        if (this.isExist(application)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "用户已提交过申请");
        }
        if (!user.getUserRole().equals(UserConstant.USER_ROLE_ADMIN)) {
            application.setResult(ReviewResultEnum.WAITING.getCode());
            if (!this.save(application)) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "提交申请失败");
            }
            return application.getId();
        }

        //如果是管理员则直接注销
        application.setResult(ReviewResultEnum.ACCEPT.getCode());
        if (!this.save(application)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "提交申请失败");
        }
        Review review = new Review();
        review.setUserId(userId);
        review.setType(ApplicationTypeEnum.DELETE_USER.getCode());
        review.setApplicationId(application.getId());
        review.setContent("管理员注销");
        review.setResult(ReviewResultEnum.ACCEPT.getCode());
        if (!reviewService.save(review)){
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "提交申请失败");
        }
        if (!userService.removeById(user)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "注销失败");
        }
        return application.getId();
    }

    /**
     * 提交加入社团申请
     *
     * @param application
     * @return
     */
    public Long addJoinClubApplication(UserApplication application) {
        ClubMembership clubMembership = new ClubMembership();
        clubMembership.setClubId(application.getAdditionalInfo());
        clubMembership.setUserId(application.getUserId());
        clubMembership.setIdentity(ClubMemberRoleEnum.MEMBER.getInfo());
        clubService.addMemberToClubValidation(clubMembership);

        application.setResult(ReviewResultEnum.WAITING.getCode());
        if (this.isExist(application)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "用户已提交过申请");
        }
        if ( !this.save(application)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "提交申请失败");
        }
        return application.getId();
    }

    /**
     * 提交退出社团申请
     *
     * @param application
     * @return
     */
    public Long addQuitClubApplication(UserApplication application) {
        ClubMembership clubMembership = new ClubMembership();
        clubMembership.setUserId(application.getUserId());
        clubMembership.setClubId(application.getAdditionalInfo());
        clubService.deleteMemberFromClubValidation(clubMembership, false);

        application.setResult(ReviewResultEnum.WAITING.getCode());
        if (this.isExist(application)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "用户已提交过申请");
        }
        if ( !this.save(application)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "提交申请失败");
        }
        return application.getId();
    }

    /**
     * 提交参与活动申请
     *
     * @param application
     * @return
     */
    public Long addEngageActivityApplication(UserApplication application) {
        ActivityMembership activityMembership = new ActivityMembership();
        activityMembership.setActivityId(application.getAdditionalInfo());
        activityMembership.setUserId(application.getUserId());
        activityService.updateActivityMemberValidation(activityMembership, true);

        application.setResult(ReviewResultEnum.WAITING.getCode());
        if (this.isExist(application)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "用户已提交过申请");
        }
        if (!this.save(application)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "提交申请失败");
        }
        return application.getId();
    }

    /**
     * 提交退出活动申请
     *
     * @param application
     * @return
     */
    public Long addQuitActivityApplication(UserApplication application) {
        ActivityMembership activityMembership = new ActivityMembership();
        activityMembership.setActivityId(application.getAdditionalInfo());
        activityMembership.setUserId(application.getUserId());
        activityService.updateActivityMemberValidation(activityMembership, false);

        application.setResult(ReviewResultEnum.WAITING.getCode());
        if (this.isExist(application)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "用户已提交过申请");
        }
        if (!this.save(application)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "提交申请失败");
        }
        return application.getId();
    }

    /**
     * 获取封装对象
     *
     * @param application
     * @return
     */
    @Override
    public UserApplicationVO getUserApplicationVO(UserApplication application) {
        if (application == null)
            return null;
        UserApplicationVO applicationVO = UserApplicationVO.objToVo(application);

        if (application.getType().equals(ApplicationTypeEnum.JOIN_CLUB.getCode()) ||
                application.getType().equals(ApplicationTypeEnum.QUIT_CLUB.getCode())){
            Club club = clubService.getById(application.getAdditionalInfo());
            applicationVO.setTargetName(club.getClubName());
        } else if (application.getType().equals(ApplicationTypeEnum.ENGAGE_ACTIVITY.getCode()) ||
                application.getType().equals(ApplicationTypeEnum.QUIT_ACTIVITY.getCode())){
            Activity activity = activityService.getById(application.getAdditionalInfo());
            applicationVO.setTargetName(activity.getActivityName());
        } else {
            applicationVO.setTargetName("");
        }

        if (!application.getResult().equals(ReviewResultEnum.WAITING.getCode())) {
            Long applicationId = application.getId();
            Integer applicationType = application.getType();
            applicationVO.setReviewVO(reviewService.getReviewVoByApplication(applicationId, applicationType));
        } else {
            ReviewVO reviewVO = new ReviewVO();
            reviewVO.setResult(ReviewResultEnum.WAITING.getInfo());
            applicationVO.setReviewVO(reviewVO);
        }

        User user = userService.getById(application.getUserId());
        UserVO userVO = UserVO.objToVoAllInfo(user);
        applicationVO.setUserVO(userVO);
        return applicationVO;
    }

    /**
     * 查看申请列表 (分页)
     *
     * @param queryRequest
     * @return
     */
    @Override
    public Page<UserApplicationVO> listApplicationVOForUserByPage(UserApplicationQueryRequest queryRequest) {
        // 可以看到用户自己提交的所有申请，一定有用户id，可能有type，可能有result，可能有id
        Long userId = queryRequest.getUserId();
        if (userId == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "查询参数为空");
        }
        Long additionalInfo = queryRequest.getAdditionalInfo();
        Integer type = queryRequest.getType();
        if (additionalInfo != null && type == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "缺少查询参数");
        }

        QueryWrapper<UserApplication> queryWrapper = getQueryWrapper(queryRequest);
        List<UserApplicationVO> applicationVOList = this.list(queryWrapper).stream()
                .map(application -> {
                    return this.getUserApplicationVO(application);
                })
                .collect(Collectors.toList());

        int current = queryRequest.getCurrent();
        int pageSize = queryRequest.getPageSize();
        Page<UserApplicationVO> page = new Page<>(current, pageSize);
        return page.setRecords(applicationVOList);
    }

    /**
     * 查看申请列表 (分页、社长)
     *
     * @param queryRequest
     * @return
     */
    @Override
    public Page<UserApplicationVO> listApplicationVOForManagerByPage(UserApplicationQueryRequest queryRequest, Long clubId) {
        //可以看到所管理的社团收到的所有申请：活动申请和社团申请
        Long additionalInfo = queryRequest.getAdditionalInfo();
        Integer type = queryRequest.getType();
        if (additionalInfo != null && type == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "缺少查询参数");
        }
        ApplicationTypeEnum applicationType = ApplicationTypeEnum.getByCode(type);
        if (applicationType == ApplicationTypeEnum.DELETE_USER) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "所查询的申请类型错误");
        }

        List<UserApplication> applicationList = this.getAllApplicationsOfClub(clubId);
        if(applicationType != null){
            applicationList = applicationList.stream()
                    .filter(application -> { return application.getType().equals(applicationType.getCode()); })
                    .toList();
        }
        Integer result = queryRequest.getResult();
        if(result != null){
            applicationList = applicationList.stream()
                    .filter(application -> { return application.getResult().equals(result); })
                    .toList();
        }

        List<UserApplicationVO> applicationVOList = applicationList.stream()
                .map(application -> {
                    return this.getUserApplicationVO(application);
                })
                .collect(Collectors.toList());
        int current = queryRequest.getCurrent();
        int pageSize = queryRequest.getPageSize();
        Page<UserApplicationVO> page = new Page<>(current, pageSize);
        return page.setRecords(applicationVOList);
    }

    /**
     * 查看申请列表 (分页、管理员)
     *
     * @param queryRequest
     * @return
     */
    @Override
    public Page<UserApplicationVO> listApplicationVOForAdminByPage(UserApplicationQueryRequest queryRequest) {
        Long additionalInfo = queryRequest.getAdditionalInfo();
        Integer type = queryRequest.getType();
        if (additionalInfo != null && type == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "缺少查询参数");
        }

        QueryWrapper<UserApplication> queryWrapper = getQueryWrapper(queryRequest);
        List<UserApplicationVO> applicationVOList = this.list(queryWrapper).stream()
                .map(application -> {
                    return this.getUserApplicationVO(application);
                })
                .collect(Collectors.toList());

        int current = queryRequest.getCurrent();
        int pageSize = queryRequest.getPageSize();
        Page<UserApplicationVO> page = new Page<>(current, pageSize);
        return page.setRecords(applicationVOList);
    }

    /**
     * 申请是否存在
     *
     * @param applicationId
     * @return
     */
    @Override
    public boolean isExist(Long applicationId) {
        if (applicationId == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "参数为空");
        }
        return this.getById(applicationId) != null;
    }

    /**
     * 申请是否存在
     *
     * @param applicationId
     * @param type
     * @return
     */
    @Override
    public boolean isExist(Long applicationId, Integer type) {
        if (applicationId == null || type == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "缺少参数");
        }
        UserApplication application = this.getById(applicationId);
        if (application != null) {
            return application.getType().equals(type);
        }
        return false;
    }

    /**
     * 申请是否存在
     * @param application 申请对象
     * @return 是否存在
     */
    @Override
    public boolean isExist(UserApplication application) {
        if (application == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "参数为空");
        }
        QueryWrapper<UserApplication> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("result", ReviewResultEnum.WAITING.getCode());  //只查待审核的申请
        queryWrapper.eq("type", application.getType());
        queryWrapper.eq("userId", application.getUserId());
        queryWrapper.eq("additionalInfo", application.getAdditionalInfo());
        return this.count(queryWrapper) > 0;
    }

    /**
     * 集合中的申请是否都审核完成
     * @param applicationList
     * @return
     */
    @Override
    public boolean isApplicationsAllReview(List<UserApplication> applicationList){
        if (!applicationList.isEmpty())
            for (UserApplication application : applicationList){
                if (application.getResult().equals(ReviewResultEnum.WAITING.getCode()))
                    return false;
            }
        return true;
    }

    /**
     * 获取查询封装
     *
     * @param queryRequest
     * @return
     */
    @Override
    public QueryWrapper<UserApplication> getQueryWrapper(UserApplicationQueryRequest queryRequest) {
        Long id = queryRequest.getId();
        Long userId = queryRequest.getUserId();
        Integer result = queryRequest.getResult();
        Integer type = queryRequest.getType();
        Long additionalInfo = queryRequest.getAdditionalInfo();

        QueryWrapper<UserApplication> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(ObjectUtils.isNotEmpty(id), "id", id);
        queryWrapper.eq(ObjectUtils.isNotEmpty(userId), "userId", userId);
        queryWrapper.eq(ObjectUtils.isNotEmpty(result), "result", result);
        if (type == null) {
            queryWrapper.orderByDesc("createTime");  // 默认按创建时间降序排序
            return queryWrapper;
        }

        queryWrapper.eq("type", type);
        queryWrapper.eq(ObjectUtils.isNotEmpty(additionalInfo), "additionalInfo", additionalInfo);
        queryWrapper.orderByDesc("createTime");  // 默认按创建时间降序排序
        return queryWrapper;
    }

    /**
     * 获取社团收到的申请列表
     * @param clubId
     * @return
     */
    @Override
    public List<UserApplication> getAllApplicationsOfClub(Long clubId) {
        return this.baseMapper.getAllApplicationsOfClub(clubId);
    }

    @Override
    public Page<UserApplication> getAllUserApplications(PageQueryRequest page) {
        int current = page.getCurrent();
        int pageSize = page.getPageSize();
        String query= page.getQuery();
        Page<UserApplication> iPage=new Page<UserApplication>().setCurrent(current).setSize(pageSize);
        LambdaQueryWrapper<UserApplication> queryWrapper=new LambdaQueryWrapper<>();
        if(query!=null){
            queryWrapper.like(UserApplication::getUserId,query).or().like(UserApplication::getAdditionalInfo,query);
        }
        List<UserApplication> list = this.list(iPage, queryWrapper);
        iPage.setRecords(list).setTotal(iPage.getTotal());
        return iPage;
    }

    private void actionUserApplication(Long id,ReviewResultEnum reviewResultEnum){
        if(this.getById(id).getResult()!=ReviewResultEnum.WAITING.getCode()){
            throw new BusinessException(ErrorCode.OPERATION_ERROR,"审核已被处理");
        }
        UserApplication byId = this.getById(id);
        byId.setResult(reviewResultEnum.getCode());
        this.updateById(byId);
    }

    @Override
    @Transactional
    public void deleteUserApplications(List<Long> ids) {
        ids.forEach(e->{
            if(this.getById(e)==null){
                throw new BusinessException(ErrorCode.OPERATION_ERROR,"该审核被删除或不存在");
            }
            this.removeById(e);
        });
    }
}




